package boot.spring.controller;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import boot.spring.pagemodel.Process;
import boot.spring.mapper.LeaveApplyMapper;
import boot.spring.pagemodel.DataGrid;
import boot.spring.pagemodel.HistoryProcess;
import boot.spring.pagemodel.LeaveTask;
import boot.spring.pagemodel.MSG;
import boot.spring.po.LeaveApply;
import boot.spring.service.LeaveService;
import boot.spring.service.SystemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api(value = "请假流程接口")
@Controller
public class ActivityController {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private FormService formService;

    @Resource
    private IdentityService identityService;

    @Resource
    private LeaveService leaveService;

    @Resource
    private TaskService taskService;

    @Resource
    private HistoryService historyService;

    @Resource
    private SystemService systemService;

    @Resource
    private LeaveApplyMapper leaveApplyMapper;

    @RequestMapping(value = "/processlist", method = RequestMethod.GET)
    String process() {
        return "activiti/processlist";
    }

    @ApiOperation("上传一个工作流文件")
    @RequestMapping(value = "/uploadworkflow", method = RequestMethod.POST)
    public String fileupload(@RequestParam MultipartFile uploadfile, HttpServletRequest request) {
        try {
            String filename = uploadfile.getOriginalFilename();
            InputStream is = uploadfile.getInputStream();
            repositoryService.createDeployment().addInputStream(filename, is).deploy();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "index";
    }

    @ApiOperation("查询已部署工作流列表")
    @RequestMapping(value = "/getprocesslists", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<Process> getList(@RequestParam("current") int current, @RequestParam("rowCount") int rowCount) {
        int firstrow = (current - 1) * rowCount;
        List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery().listPage(firstrow, rowCount);
        int total = repositoryService.createProcessDefinitionQuery().list().size();
        List<Process> processList = new ArrayList<>();
        for (ProcessDefinition processDefinition : processDefinitionList) {
            Process process = new Process();
            process.setDeploymentId(processDefinition.getDeploymentId());
            process.setId(processDefinition.getId());
            process.setKey(processDefinition.getKey());
            process.setName(processDefinition.getName());
            process.setResourceName(processDefinition.getResourceName());
            process.setDiagramresourcename(processDefinition.getDiagramResourceName());
            processList.add(process);
        }
        DataGrid<Process> grid = new DataGrid<>();
        grid.setCurrent(current);
        grid.setRowCount(rowCount);
        grid.setRows(processList);
        grid.setTotal(total);
        return grid;
    }

    @ApiOperation("查看工作流图片")
    @RequestMapping(value = "/showresource", method = RequestMethod.GET)
    public void export(@RequestParam("pdid") String pdId, @RequestParam("resource") String resource,
                       HttpServletResponse response) throws Exception {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(pdId).singleResult();
        InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resource);
        ServletOutputStream output = response.getOutputStream();
        IOUtils.copy(inputStream, output);
    }

    @RequestMapping(value = "/deletedeploy", method = RequestMethod.POST)
    public String deleteDeploy(@RequestParam("deployid") String deployId) {
        repositoryService.deleteDeployment(deployId, true);
        return "activiti/processlist";
    }

    @RequestMapping(value = "/runningprocess", method = RequestMethod.GET)
    public String task() {
        return "activiti/runningprocess";
    }

    @RequestMapping(value = "/deptleaderaudit", method = RequestMethod.GET)
    public String mytask() {
        return "activiti/deptleaderaudit";
    }

    @RequestMapping(value = "/hraudit", method = RequestMethod.GET)
    public String hr() {
        return "activiti/hraudit";
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String my() {
        return "index";
    }

    @RequestMapping(value = "/leaveapply", method = RequestMethod.GET)
    public String leave() {
        return "activiti/leaveapply";
    }

    @RequestMapping(value = "/reportback", method = RequestMethod.GET)
    public String reprotback() {
        return "activiti/reportback";
    }

    @RequestMapping(value = "/modifyapply", method = RequestMethod.GET)
    public String modifyapply() {
        return "activiti/modifyapply";
    }

    @ApiOperation("发起一个请假流程")
    @RequestMapping(value = "/startleave", method = RequestMethod.POST)
    @ResponseBody
    public MSG start_leave(LeaveApply apply, HttpSession session) {
        String userid = (String) session.getAttribute("username");
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("applyuserid", userid);
        variables.put("deptleader", apply.getDeptleader());
        leaveService.startWorkflow(apply, userid, variables);
        return new MSG("sucess");
    }

    @ApiOperation("获取部门领导审批待办列表")
    @RequestMapping(value = "/depttasklist", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<LeaveTask> getDeptTaskList(HttpSession session,
                                               @RequestParam("current") int current,
                                               @RequestParam("rowCount") int rowCount) {
        String username = (String) session.getAttribute("username");
        DataGrid<LeaveTask> grid = new DataGrid<LeaveTask>();
        grid.setRowCount(rowCount);
        grid.setCurrent(current);
        int firstRow = (current - 1) * rowCount;
        List<LeaveApply> results = leaveService.getPageDeptTask(username, firstRow, rowCount);
        int totalsize = leaveService.getAllDeptTask(username);
        List<LeaveTask> tasks = new ArrayList<LeaveTask>();
        for (LeaveApply apply : results) {
            LeaveTask task = new LeaveTask();
            task.setApply_time(apply.getApply_time());
            task.setUser_id(apply.getUser_id());
            task.setEnd_time(apply.getEnd_time());
            task.setId(apply.getId());
            task.setLeave_type(apply.getLeave_type());
            task.setProcess_instance_id(apply.getProcess_instance_id());
            task.setProcessdefid(apply.getTask().getProcessDefinitionId());
            task.setReason(apply.getReason());
            task.setStart_time(apply.getStart_time());
            task.setTaskcreatetime(apply.getTask().getCreateTime());
            task.setTaskid(apply.getTask().getId());
            task.setTaskname(apply.getTask().getName());
            tasks.add(task);
        }
        grid.setTotal(totalsize);
        grid.setRows(tasks);
        return grid;
    }

    @ApiOperation("获取人事审批待办列表")
    @RequestMapping(value = "/hrtasklist", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<LeaveTask> gethrtasklist(HttpSession session, @RequestParam("current") int current,
                                             @RequestParam("rowCount") int rowCount) {
        DataGrid<LeaveTask> grid = new DataGrid<LeaveTask>();
        grid.setRowCount(rowCount);
        grid.setCurrent(current);
        String username = (String) session.getAttribute("username");
        int firstrow = (current - 1) * rowCount;
        List<LeaveApply> results = leaveService.getPageHrTask(username, firstrow, rowCount);
        int totalsize = leaveService.getallhrtask(username);
        List<LeaveTask> tasks = new ArrayList<LeaveTask>();
        for (LeaveApply apply : results) {
            LeaveTask task = new LeaveTask();
            task.setApply_time(apply.getApply_time());
            task.setUser_id(apply.getUser_id());
            task.setEnd_time(apply.getEnd_time());
            task.setId(apply.getId());
            task.setLeave_type(apply.getLeave_type());
            task.setProcess_instance_id(apply.getProcess_instance_id());
            task.setProcessdefid(apply.getTask().getProcessDefinitionId());
            task.setReason(apply.getReason());
            task.setStart_time(apply.getStart_time());
            task.setTaskcreatetime(apply.getTask().getCreateTime());
            task.setTaskid(apply.getTask().getId());
            task.setTaskname(apply.getTask().getName());
            tasks.add(task);
        }
        grid.setRowCount(rowCount);
        grid.setCurrent(current);
        grid.setTotal(totalsize);
        grid.setRows(tasks);
        return grid;
    }

    @ApiOperation("获取销假任务列表")
    @RequestMapping(value = "/xjtasklist", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<LeaveTask> getXJtasklist(HttpSession session, @RequestParam("current") int current,
                                             @RequestParam("rowCount") int rowCount) {
        int firstrow = (current - 1) * rowCount;
        String userid = (String) session.getAttribute("username");
        List<LeaveApply> results = leaveService.getpageXJtask(userid, firstrow, rowCount);
        int totalsize = leaveService.getallXJtask(userid);
        List<LeaveTask> tasks = new ArrayList<LeaveTask>();
        for (LeaveApply apply : results) {
            LeaveTask task = new LeaveTask();
            task.setApply_time(apply.getApply_time());
            task.setUser_id(apply.getUser_id());
            task.setEnd_time(apply.getEnd_time());
            task.setId(apply.getId());
            task.setLeave_type(apply.getLeave_type());
            task.setProcess_instance_id(apply.getProcess_instance_id());
            task.setProcessdefid(apply.getTask().getProcessDefinitionId());
            task.setReason(apply.getReason());
            task.setStart_time(apply.getStart_time());
            task.setTaskcreatetime(apply.getTask().getCreateTime());
            task.setTaskid(apply.getTask().getId());
            task.setTaskname(apply.getTask().getName());
            tasks.add(task);
        }
        DataGrid<LeaveTask> grid = new DataGrid<LeaveTask>();
        grid.setRowCount(rowCount);
        grid.setCurrent(current);
        grid.setTotal(totalsize);
        grid.setRows(tasks);
        return grid;
    }

    @ApiOperation("获取调整休假申请任务列表")
    @RequestMapping(value = "/updatetasklist", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<LeaveTask> getupdatetasklist(HttpSession session, @RequestParam("current") int current,
                                                 @RequestParam("rowCount") int rowCount) {
        int firstrow = (current - 1) * rowCount;
        String userid = (String) session.getAttribute("username");
        List<LeaveApply> results = leaveService.getpageupdateapplytask(userid, firstrow, rowCount);
        int totalsize = leaveService.getallupdateapplytask(userid);
        List<LeaveTask> tasks = new ArrayList<LeaveTask>();
        for (LeaveApply apply : results) {
            LeaveTask task = new LeaveTask();
            task.setApply_time(apply.getApply_time());
            task.setUser_id(apply.getUser_id());
            task.setEnd_time(apply.getEnd_time());
            task.setId(apply.getId());
            task.setLeave_type(apply.getLeave_type());
            task.setProcess_instance_id(apply.getProcess_instance_id());
            task.setProcessdefid(apply.getTask().getProcessDefinitionId());
            task.setReason(apply.getReason());
            task.setStart_time(apply.getStart_time());
            task.setTaskcreatetime(apply.getTask().getCreateTime());
            task.setTaskid(apply.getTask().getId());
            task.setTaskname(apply.getTask().getName());
            tasks.add(task);
        }
        DataGrid<LeaveTask> grid = new DataGrid<LeaveTask>();
        grid.setRowCount(rowCount);
        grid.setCurrent(current);
        grid.setTotal(totalsize);
        grid.setRows(tasks);
        return grid;
    }

    @ApiOperation("使用任务id获取请假业务数据")
    @RequestMapping(value = "/dealtask", method = RequestMethod.POST)
    @ResponseBody
    public LeaveApply taskdeal(@RequestParam("taskid") String taskid, HttpServletResponse response) {
        Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
        ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId())
                .singleResult();
        return leaveService.getleave(new Integer(process.getBusinessKey()));
    }

    @RequestMapping(value = "/activiti/task-deptleaderaudit", method = RequestMethod.GET)
    String url() {
        return "/activiti/task-deptleaderaudit";
    }

    @ApiOperation("完成部门领导审批待办")
    @RequestMapping(value = "/task/deptcomplete/{taskid}", method = RequestMethod.POST)
    @ResponseBody
    public MSG deptcomplete(HttpSession session, @PathVariable("taskid") String taskid, HttpServletRequest req) {
        String username = (String) session.getAttribute("username");
        Map<String, Object> variables = new HashMap<String, Object>();
        String approve = req.getParameter("deptleaderapprove");
        String hr = req.getParameter("hr");
        variables.put("deptleaderapprove", approve);
        variables.put("hr", hr);
        taskService.claim(taskid, username);
        taskService.complete(taskid, variables);
        return new MSG("success");
    }

    @ApiOperation("完成hr审批待办")
    @RequestMapping(value = "/task/hrcomplete/{taskid}", method = RequestMethod.POST)
    @ResponseBody
    public MSG hrcomplete(HttpSession session, @PathVariable("taskid") String taskid, HttpServletRequest req) {
        String userid = (String) session.getAttribute("username");
        Map<String, Object> variables = new HashMap<String, Object>();
        String approve = req.getParameter("hrapprove");
        variables.put("hrapprove", approve);
        taskService.claim(taskid, userid);
        taskService.complete(taskid, variables);
        return new MSG("success");
    }

    @ApiOperation("完成销假待办")
    @RequestMapping(value = "/task/reportcomplete/{taskid}", method = RequestMethod.POST)
    @ResponseBody
    public MSG reportbackcomplete(@PathVariable("taskid") String taskid, HttpServletRequest req) {
        String realstart_time = req.getParameter("realstart_time");
        String realend_time = req.getParameter("realend_time");
        leaveService.completeReportBack(taskid, realstart_time, realend_time);
        return new MSG("success");
    }

    @ApiOperation("完成调整申请待办")
    @RequestMapping(value = "/task/updatecomplete/{taskid}", method = RequestMethod.POST)
    @ResponseBody
    public MSG updatecomplete(@PathVariable("taskid") String taskid, @ModelAttribute("leave") LeaveApply leave,
                              @RequestParam("reapply") String reapply) {
        leaveService.updateComplete(taskid, leave, reapply);
        return new MSG("success");
    }

    @RequestMapping(value = "/getfinishprocess", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<HistoryProcess> getHistory(HttpSession session, @RequestParam("current") int current,
                                               @RequestParam("rowCount") int rowCount) {
        String userid = (String) session.getAttribute("username");
        HistoricProcessInstanceQuery process = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionKey("leave").startedBy(userid).finished();
        int total = (int) process.count();
        int firstrow = (current - 1) * rowCount;
        List<HistoricProcessInstance> info = process.listPage(firstrow, rowCount);
        List<HistoryProcess> list = new ArrayList<HistoryProcess>();
        for (HistoricProcessInstance history : info) {
            HistoryProcess his = new HistoryProcess();
            String bussinesskey = history.getBusinessKey();
            LeaveApply apply = leaveService.getleave(Integer.parseInt(bussinesskey));
            his.setLeaveapply(apply);
            his.setBusinessKey(bussinesskey);
            his.setProcessDefinitionId(history.getProcessDefinitionId());
            list.add(his);
        }
        DataGrid<HistoryProcess> grid = new DataGrid<HistoryProcess>();
        grid.setCurrent(current);
        grid.setRowCount(rowCount);
        grid.setTotal(total);
        grid.setRows(list);
        return grid;
    }

    @RequestMapping(value = "/historyprocess", method = RequestMethod.GET)
    public String history() {
        return "activiti/historyprocess";
    }

    @ApiOperation("使用流程实例编号获取历史流程数据")
    @RequestMapping(value = "/processinfo", method = RequestMethod.POST)
    @ResponseBody
    public List<HistoricActivityInstance> processinfo(@RequestParam("instanceid") String instanceid) {
        return historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceid).orderByHistoricActivityInstanceStartTime().asc().list();
    }

    @ApiOperation("使用业务号获取历史流程数据")
    @RequestMapping(value = "/processhis", method = RequestMethod.POST)
    @ResponseBody
    public List<HistoricActivityInstance> processhis(@RequestParam("ywh") String ywh) {
        String instanceid = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("purchase")
                .processInstanceBusinessKey(ywh).singleResult().getId();
        return historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceid).orderByHistoricActivityInstanceStartTime().asc().list();
    }

    @RequestMapping(value = "myleaveprocess", method = RequestMethod.GET)
    String myleaveprocess() {
        return "activiti/myleaveprocess";
    }

    @ApiOperation("使用executionid追踪流程图进度")
    @RequestMapping(value = "traceprocess/{executionid}", method = RequestMethod.GET)
    public void traceprocess(@PathVariable("executionid") String executionid, HttpServletResponse response) throws Exception {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionid).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionid);
        DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
        // 获得历史活动记录实体（通过启动时间正序排序，不然有的线可以绘制不出来）
        List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                .executionId(executionid).orderByHistoricActivityInstanceStartTime().asc().list();
        // 计算活动线
        List<String> highLightedFlows = leaveService.getHighLightedFlows((ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processInstance.getProcessDefinitionId()), historicActivityInstances);

        InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows, "宋体", "宋体", null, null, 1.0);
        // InputStream in=gen.generateDiagram(bpmnmodel, "png", activeActivityIds);
        ServletOutputStream outputStream = response.getOutputStream();
        IOUtils.copy(inputStream, outputStream);
    }

    @RequestMapping(value = "myleaves", method = RequestMethod.GET)
    String myleaves() {
        return "activiti/myleaves";
    }

    @ApiOperation("我发起的请假流程")
    @RequestMapping(value = "setupprocess", method = RequestMethod.POST)
    @ResponseBody
    public DataGrid<LeaveApply> setupprocess(HttpSession session, @RequestParam("current") int current,
                                             @RequestParam("rowCount") int rowCount) {
        String username = (String) session.getAttribute("username");
        List<LeaveApply> list = leaveService.getPageByApplyer(username, current, rowCount);
        for (LeaveApply apply : list) {
            ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(apply.getProcess_instance_id()).singleResult();
            if (process == null) {
                apply.setState("已结束");
                apply.setActivityid("无");
            } else {
                apply.setState("运行中");
                apply.setActivityid(process.getActivityId());
            }
        }
        DataGrid<LeaveApply> grid = new DataGrid<LeaveApply>();
        grid.setCurrent(current);
        grid.setRowCount(rowCount);
        grid.setTotal(leaveService.getAllByApplyer(username));
        grid.setRows(list);
        return grid;
    }

}
